package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzyl.constant.CacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.StringUtils;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @FileName ResourceServiceImpl
 * @Description
 * @Author Sword
 * @date 2025-10-06
 **/

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * 资源列表
     *
     * @param resourceDto
     * @return
     */
    @Override
    @Cacheable(cacheNames = CacheConstant.RESOURCE_LIST, key = "#resourceDto.hashCode()")
    public List<ResourceVo> list(ResourceDto resourceDto) {
        List<Resource> resources = resourceMapper.list(resourceDto);
        return BeanUtil.copyToList(resources, ResourceVo.class);
    }

    /**
     * 资源树形
     *
     * @param resourceDto
     * @return
     */
    @Override
    @Cacheable(cacheNames = CacheConstant.RESOURCE_TREE)
    public TreeVo tree(ResourceDto resourceDto) {
        //构建查询条件
        resourceDto.setDataState(SuperConstant.DATA_STATE_0);
        resourceDto.setParentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID));
        resourceDto.setResourceType(SuperConstant.MENU);

        //查询资源信息
        List<Resource> resources = resourceMapper.list(resourceDto);

        if (EmptyUtil.isNullOrEmpty(resources)) {
            throw new RuntimeException("资源信息未定义");
        }

        //创建根节点
        Resource resource = new Resource();
        resource.setResourceNo(SuperConstant.ROOT_PARENT_ID);
        resource.setResourceName("智慧养老院");

        //创建树形集合
        List<TreeItemVo> treeItemVos = new ArrayList<>();

        //递归创建树形结构
        recursionTree(treeItemVos, resource, resources);

        return TreeVo.builder().items(treeItemVos).build();
    }

    /**
     * 资源添加
     *
     * @param resourceDto
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_LIST, allEntries = true),
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_TREE, allEntries = true)
            }
    )
    @Override
    public void createResource(ResourceDto resourceDto) {
        //对象拷贝
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);

        //查询父资源数据状态
        Resource parentResource = resourceMapper.getByResourceNo(resource.getParentResourceNo());
        resource.setDataState(parentResource.getDataState());

        //true:菜单 false:按钮
        boolean isIgnore = true;

        if (StringUtils.isNotEmpty(resource.getResourceType()) && resource.getResourceType().equals(SuperConstant.BUTTON)) {
            isIgnore = false;
        }

        //生成资源编号
        String resourceNo = createResourceNo(resource.getParentResourceNo(), isIgnore);
        resource.setResourceNo(resourceNo);

        //插入资源数据
        resourceMapper.insert(resource);
    }

    /**
     * 资源修改
     *
     * @param resourceDto
     * @return
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_LIST, allEntries = true),
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_TREE, allEntries = true)
            }
    )
    @Override
    public void updateResource(ResourceDto resourceDto) {
        //对象拷贝
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);

        //如果资源下级菜单有关联资源则不允许修改
        //根据id查询资源信息
        Resource r = resourceMapper.selectByPrimaryKey(resource.getId());
        if (r.getResourceType().equals(SuperConstant.MENU)) {
            //查询子资源
            ResourceDto rd = ResourceDto.builder().parentResourceNo(resource.getResourceNo()).build();
            List<Resource> resources = resourceMapper.list(rd);
            if (!EmptyUtil.isNullOrEmpty(resources)) {
                throw new RuntimeException("菜单下有子菜单或按钮，请先删除");
            }
        }

        //没有子菜单
        //修改父资源编号
        if (!resource.getParentResourceNo().equals(r.getParentResourceNo())) {
            String resourceNo = createResourceNo(resource.getParentResourceNo(), true);
            resource.setResourceNo(resourceNo);
        }

        resourceMapper.updateByPrimaryKeySelective(resource);

    }

    /**
     * 启用禁用
     *
     * @param resourceDto
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_LIST, allEntries = true),
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_TREE, allEntries = true)
            }
    )
    @Override
    public void enable(ResourceDto resourceDto) {
        Resource resource = BeanUtil.copyProperties(resourceDto, Resource.class);

        ResourceDto dto = ResourceDto.builder().parentResourceNo(resource.getResourceNo()).resourceNo(resource.getResourceNo()).dataState(SuperConstant.DATA_STATE_0).build();

        List<Resource> resources = resourceMapper.list(dto);
        if (!EmptyUtil.isNullOrEmpty(resources)) {
            throw new RuntimeException("菜单下有子菜单或按钮，请先禁用");
        }
        Resource r = resourceMapper.getByResourceNo(resource.getResourceNo());
        resource.setId(r.getId());

        resourceMapper.updateByPrimaryKeySelective(resource);

    }

    /**
     * 删除菜单
     *
     * @param resourceNo
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_LIST, allEntries = true),
                    @CacheEvict(cacheNames = CacheConstant.RESOURCE_TREE, allEntries = true)
            }
    )
    @Override
    public void delete(String resourceNo) {
        ResourceDto resourceDto = ResourceDto.builder().parentResourceNo(resourceNo).build();

        List<Resource> resources = resourceMapper.list(resourceDto);
        if (!EmptyUtil.isNullOrEmpty(resources)) {
            throw new RuntimeException("菜单下有子菜单或按钮，请先删除");
        }

        resourceMapper.deleteByResourceNo(resourceNo);
    }

    /**
     * 动态菜单
     *
     * @param userId
     * @return
     */
    @Override
    public List<MenuVo> menus(Long userId) {
        //查询用户对应的所有菜单
        List<MenuVo> menuVoList = resourceMapper.findListByUserId(userId);

        if (EmptyUtil.isNullOrEmpty(menuVoList)) {
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
        }

        //对数据进行分组
        Map<String, List<MenuVo>> parentMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));

        //遍历所有数据
        menuVoList.forEach(menuVo -> {
            menuVo.setRedirect("/" + menuVo.getName());
            menuVo.setMeta(
                    MenuMetaVo.builder()
                            .title(menuVo.getName())
                            .build()
            );
            //根据父资源编号到map集合中找是否包含子菜单,如果包含设置为当前菜单的子菜单
            List<MenuVo> childMenus = parentMap.get(menuVo.getResourceNo());

            if (!EmptyUtil.isNullOrEmpty(childMenus)) {
                childMenus.forEach(childMenu -> {
                    childMenu.setRedirect("/" + childMenu.getName());
                    childMenu.setMeta(
                            MenuMetaVo.builder()
                                    .title(childMenu.getName())
                                    .build()
                    );
                });
            }

            menuVo.setChildren(childMenus);
        });

        //根据根编号查询所有子菜单
        return parentMap.get(SuperConstant.ROOT_PARENT_ID);
    }

    private String createResourceNo(String parentResourceNo, boolean isIgnore) {
        //判断菜单是否大于三级
        if (isIgnore && NoProcessing.processString(parentResourceNo).length() / 3 >= 5) {
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }

        ResourceDto resourceDto = ResourceDto.builder().parentResourceNo(parentResourceNo).build();
        //根据父资源编号查询
        List<Resource> resources = resourceMapper.list(resourceDto);

        //为空生成新的子编号，否则根据已有子编号追加
        if (EmptyUtil.isNullOrEmpty(resources)) {
            return NoProcessing.createNo(parentResourceNo, false);
        } else {
            //获取最大子编号
            Long maxResourceNo = resources.stream().map(resource -> Long.valueOf(resource.getResourceNo())).max(Comparator.comparing(i -> i)).get();

            return NoProcessing.createNo(String.valueOf(maxResourceNo), true);
        }
    }

    private void recursionTree(List<TreeItemVo> treeItemVos, Resource resource, List<Resource> resources) {
        //构建根节点item
        TreeItemVo root = TreeItemVo.builder().id(resource.getResourceNo()).label(resource.getResourceName()).build();

        //获取子资源
        List<Resource> resourceChildList = resources.stream().filter(n -> n.getParentResourceNo().equals(resource.getResourceNo())).collect(Collectors.toList());

        //子资源不为空递归
        if (!EmptyUtil.isNullOrEmpty(resourceChildList)) {
            //创建子节点集合
            List<TreeItemVo> childList = new ArrayList<>();

            //创建子资源
            resourceChildList.forEach(r -> {
                recursionTree(childList, r, resources);
            });
            root.setChildren(childList);
        }

        //添加到集合中
        treeItemVos.add(root);
    }
}
